#import "layer_game_object.h"

#define ARROW_COOL_DOWN_TIME_TURBO 0.05

/*touch type
*/
#define LAYER_GAME_OBJECT_TOUCH_TYPE_INVALID 0
#define LAYER_GAME_OBJECT_TOUCH_TYPE_PARABOLA 1
#define LAYER_GAME_OBJECT_TOUCH_TYPE_LINEAR 2
#define LAYER_GAME_OBJECT_TOUCH_TYPE_ITEM 3

/*z order
*/
#define Z_ORDER_NORMAL 0
#define Z_ORDER_BOW 1
#define Z_ORDER_SWIRL 2
#define Z_ORDER_ARROW 3
#define Z_ORDER_ARROW_PARTICLE 4
#define Z_ORDER_ENEMY_MOUTH_ATTACK 5
#define Z_ORDER_HEART 6
#define Z_ORDER_ENEMY 7
#define Z_ORDER_ENEMY_BOSS 9
#define Z_ORDER_BOMB 10
#define Z_ORDER_TIME_BAR 11
#define Z_ORDER_TIMER 12
#define Z_ORDER_ITEM 13
#define Z_ORDER_BOSS_3_QTE 14
#define Z_ORDER_TOTURIAL 15

/*collision type
*/
#define COLLISION_TYPE_INVALID 0
#define COLLISION_TYPE_ARROW 1
#define COLLISION_TYPE_ENEMY 2
#define COLLISION_TYPE_BOMB 3
#define COLLISION_TYPE_HEART 4
#define COLLISION_TYPE_STAR 5

#define LAYER_GAME_OBJECT_CREATE_STAR_TIME 60.0f

@implementation LayerGameObject

@synthesize flagTouchLock = flagTouchLock_;
@synthesize flagTouchLockArrow = flagTouchLockArrow_;
@synthesize flagTouchLockItem = flagTouchLockItem_;
@synthesize startPos = startPos_;
@synthesize flagFunctionLock = flagFunctionLock_;

- (id)initLayerGameObject
{
	int _Index;
	float _HandleFlagW2;
	float _HandleFlagH2;
	float _ItemSizeW2;
	float _ItemSizeH2;
	b2Vec2 _Temp;

	if ((self = [super init]))
	{
		/*load resource
		*/
		reLoadResource(&g_CfgGameBaseResourceTable);
		reLoadResource(&g_CfgGameBowResourceTable.find(g_RecordWeapSelected)->second);
		reLoadResource(&g_CfgGameItemResourceTable);

		/*set up tick update
		*/
		[self schedule:@selector(tick:)];

		/*flag
		*/
		flagTouchLock_ = true;
		flagFunctionLock_ = true;

		/*initialization opengl data
		*/
		_HandleFlagW2 = g_CfgGameParabolaTouch.width / 2;
		_HandleFlagH2 = g_CfgGameParabolaTouch.height / 2;
		_ItemSizeW2 = 50 / 2;
		_ItemSizeH2 = 50 / 2;

		_Index = 0;
		indexArray_[_Index++] = 0;
		indexArray_[_Index++] = 1;
		indexArray_[_Index++] = 1;
		indexArray_[_Index++] = 2;
		indexArray_[_Index++] = 2;
		indexArray_[_Index++] = 3;
		indexArray_[_Index++] = 3;
		indexArray_[_Index++] = 0;
		_Index = 0;
		arrowHandleFlag_[_Index++] = -_HandleFlagW2;
		arrowHandleFlag_[_Index++] = _HandleFlagH2;
		arrowHandleFlag_[_Index++] = _HandleFlagW2;
		arrowHandleFlag_[_Index++] = _HandleFlagH2;
		arrowHandleFlag_[_Index++] = _HandleFlagW2;
		arrowHandleFlag_[_Index++] = -_HandleFlagH2;
		arrowHandleFlag_[_Index++] = -_HandleFlagW2;
		arrowHandleFlag_[_Index++] = -_HandleFlagH2;
		_Index = 0;
		itemBarVertexArray_[_Index++] = -_ItemSizeW2;
		itemBarVertexArray_[_Index++] = _ItemSizeH2;
		itemBarVertexArray_[_Index++] = _ItemSizeW2;
		itemBarVertexArray_[_Index++] = _ItemSizeH2;
		itemBarVertexArray_[_Index++] = _ItemSizeW2;
		itemBarVertexArray_[_Index++] = -_ItemSizeH2;
		itemBarVertexArray_[_Index++] = -_ItemSizeW2;
		itemBarVertexArray_[_Index++] = -_ItemSizeH2;

		/*initialization touch data
		*/
		flagTouchLockArrow_ = false;
		flagTouchLockItem_ = false;
		touchType_ = LAYER_GAME_OBJECT_TOUCH_TYPE_INVALID;

		startPos_ = g_CfgGameBowBase;
		endPos_ = startPos_;

		touchRegisterList_.clear();

		/*initialization bow object
		*/
		flagLinearAutoDrag_ = false;
		flagLinearAutoDragComplete_ = false;
		flagLinearAutoDragCompleteRelease_ = false;
		dragDistanceRatio_ = 0.0f;
		bow_ = [[sprite_game_bow alloc] initSpriteGameBow:g_RecordWeapSelected];
		[self addChild:bow_ z:Z_ORDER_BOW];
		[bow_ release];
		[bow_ setPositionInPixels:startPos_];

		/*initialization arrow object
		*/
		arrowCoolDownTime_ = g_CfgGameArrowDataTable[g_RecordWeapSelected].cool_down_time;
		currentHandleArrowTable_.clear();
		arrowPool_.clear();

		/*initialization enemy object
		*/
		enemyPool_.clear();
		tailLeft_ = nil;
		tailRight_ = nil;

		/*initialization heart object
		*/
		heartPool_.clear();

		/*initialization birdge object
		*/
		bridge_ = [[sprite_game_bridge alloc] initSpriteGameBridge];
		[self addChild:bridge_ z:Z_ORDER_NORMAL];
		[bridge_ release];
		bridge_.positionInPixels = g_CfgGameBridgePosition;

		/*initialization time bar object
		*/
		timeBar_ = [[sprite_game_time_bar alloc] initSpriteGameTimeBar];
		[self addChild:timeBar_ z:Z_ORDER_TIME_BAR];
		[timeBar_ release];
		timeBar_.positionInPixels = g_CfgGameTimeBarPosition;

		/*initialization item object
		*/
		item_[0].type = g_RecordItemSelected[0];
		item_[0].holder = [CCSprite spriteWithFile:@"icon_propsItem.png"];
		[self addChild:item_[0].holder z:Z_ORDER_ITEM];
		item_[0].holder.positionInPixels = g_CfgGameItem1HolderPosition;
		item_[0].item = [[CCSprite alloc] init];
		[self addChild:item_[0].item];
		[item_[0].item release];
		item_[0].item.positionInPixels = g_CfgGameItem1HolderPosition;
		item_[0].item.scale = 0.5;
		item_[0].label = [CCLabelTTF labelWithString:@"0" fontName:@"courier" fontSize:24];
		[self addChild:item_[0].label z:Z_ORDER_ITEM];
		item_[0].label.positionInPixels = ccpAdd(g_CfgGameItem1HolderPosition, ccp(item_[0].holder.contentSizeInPixels.width / 4, item_[0].holder.contentSizeInPixels.height / 4));
		item_[0].rect.center = g_CfgGameItem1HolderPosition;
		item_[0].rect.size = item_[0].holder.contentSizeInPixels;

		item_[1].type = g_RecordItemSelected[1];
		item_[1].holder = [CCSprite spriteWithFile:@"icon_propsItem.png"];
		[self addChild:item_[1].holder z:Z_ORDER_ITEM];
		item_[1].holder.positionInPixels = g_CfgGameItem2HolderPosition;
		item_[1].item = [[CCSprite alloc] init];
		[self addChild:item_[1].item];
		[item_[1].item release];
		item_[1].item.positionInPixels = g_CfgGameItem2HolderPosition;
		item_[1].item.scale = 0.5;
		item_[1].label = [CCLabelTTF labelWithString:@"0" fontName:@"courier" fontSize:24];
		[self addChild:item_[1].label z:Z_ORDER_ITEM];
		item_[1].label.positionInPixels = ccpAdd(g_CfgGameItem2HolderPosition, ccp(item_[1].holder.contentSizeInPixels.width / 4, item_[1].holder.contentSizeInPixels.height / 4));
		item_[1].rect.center = g_CfgGameItem2HolderPosition;
		item_[1].rect.size = item_[1].holder.contentSizeInPixels;

		[self UpdateItem];

		flagExplodeArrow_ = false;
		flagMultiArrowTimes_ = 0;

		/*initialization collision data
		*/
		contactPool_.clear();
		destroyBodyPool_.clear();

		/*initialization timer flag
		*/
		timerFlagCoolDown_ = [CCProgressTimer progressWithFile:@"timer_flag_cool_down.png"];
		[self addChild:timerFlagCoolDown_ z:Z_ORDER_TIMER];
		timerFlagLevelUp_ = [CCProgressTimer progressWithFile:@"timer_flag_level_up.png"];
		[self addChild:timerFlagLevelUp_ z:Z_ORDER_TIMER];
		timerFlagCoolDown_.positionInPixels = startPos_;
		timerFlagCoolDown_.type = kCCProgressTimerTypeRadialCW;
		timerFlagLevelUp_.positionInPixels = startPos_;
		timerFlagLevelUp_.type = kCCProgressTimerTypeRadialCW;

		/*menu btn
		*/
		btnMenu_ = CREATE_BTN_MENU(CallBackBtnMenu);
		btnMenu_.anchorPoint = ccp(0.9f, 0.0f);
		btnMenu_.positionInPixels = ccp(g_ScrrenSize.width + btnMenu_.contentSizeInPixels.width, 0.0f);
		uiNodeAddMenu(self, CGPointZero, btnMenu_, nil);
	}
	return self;
}

- (void)dealloc
{
	/*release resource
	*/
	reFreeResource(&g_CfgGameBowResourceTable.find(g_RecordWeapSelected)->second);

	[super dealloc];
}

- (void)draw
{
#if 0
	/*arrow handle flag
	*/
	glDisable(GL_TEXTURE_2D);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_COLOR_ARRAY);

	glLineWidth(1.0f);
	glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
	glVertexPointer(2, GL_FLOAT, 0, arrowHandleFlag_);
	glPushMatrix();
	glTranslatef(endPos_.x, endPos_.y, 0.0f);
	glDrawElements(GL_LINES, 8, GL_UNSIGNED_BYTE, indexArray_);
	glPopMatrix();

	glEnable(GL_TEXTURE_2D);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnableClientState(GL_COLOR_ARRAY);

	/*area flag
	*/
	glColor4f(0.3, 0, 0, 0.1);
	uiRenderRect(g_CfgGameScrrenArea[0]);
	glColor4f(0.6, 0, 0, 0.1);
	uiRenderRect(g_CfgGameScrrenArea[1]);
	glColor4f(0.9, 0, 0, 0.1);
	uiRenderRect(g_CfgGameScrrenArea[2]);

	glColor4f(0, 0.3, 0, 0.1);
	uiRenderRect(g_CfgGameScrrenArea[3]);
	glColor4f(0, 0.6, 0, 0.1);
	uiRenderRect(g_CfgGameScrrenArea[4]);
	glColor4f(0, 0.9, 0, 0.1);
	uiRenderRect(g_CfgGameScrrenArea[5]);

	glColor4f(0, 0, 0.3, 0.1);
	uiRenderRect(g_CfgGameScrrenArea[6]);
	glColor4f(0, 0, 0.6, 0.1);
	uiRenderRect(g_CfgGameScrrenArea[7]);
	glColor4f(0, 0, 0.9, 0.1);
	uiRenderRect(g_CfgGameScrrenArea[8]);
#endif
}

- (void)tick:(ccTime)Time
{
	bool _Flag;
	std::list<SGameHandleArrow>::iterator _HandleArrowIter;
	std::list<SContact>::iterator _ContactIter;
	std::list<b2Body *>::iterator _DestroyBodyIter;

	/*check linear auto drag*/
	if (flagLinearAutoDrag_)
	{
		if (flagLinearAutoDragComplete_)
		{
			if (flagLinearAutoDragCompleteRelease_)
			{
				[self ReleaseLinearArrow:800];
				[self AutoDragEnd];
				endPos_ = [bow_ GetBowHandlePoint];
			}
		}
		else
		{
			_Flag = true;
			if ([currentHandleArrowTable_.begin()->arrow GetMaxDragLength] - bow_.bowBaseLength >= bow_.dragDistance)
			{
				bow_.dragDistance = bow_.dragDistance + 5.0f;
				_Flag = false;
			}
			if (_Flag)
			{
				[self AutoDragComplete];
			}
			else
			{
				_HandleArrowIter = currentHandleArrowTable_.begin();
				for (; _HandleArrowIter != currentHandleArrowTable_.end(); _HandleArrowIter++)
				{
					_HandleArrowIter->arrow.positionInPixels = [bow_ GetBowHandlePoint];
				}
			}
		}
	}

	/*check collision*/
	if (0 < contactPool_.size())
	{
		_ContactIter = contactPool_.begin();
		for (; contactPool_.end() != _ContactIter; ++_ContactIter)
		{
			[self CheckContact:&*_ContactIter];
		}
	}

	/*check destroy box2d body*/
	if (destroyBodyPool_.size() > 0)
	{
		_DestroyBodyIter = destroyBodyPool_.begin();
		for (; destroyBodyPool_.end() != _DestroyBodyIter; _DestroyBodyIter++)
		{
			CMgrGamePhysics::World()->DestroyBody(*_DestroyBodyIter);
		}
		destroyBodyPool_.clear();
	}
}

- (void)tickActionPreviewOver:(ccTime)Time
{
	[self unschedule:@selector(tickActionPreviewOver:)];

	/*change mission state
	*/
	CMgrGameMission::Instance()->SetMissionState(MISSION_STATE_LAYER_OBJECT_READY);

	/*unlock touch
	*/
	[self BowReset];
	[self ReadyArrow];
}

- (void)tickArrowCoolDownTimeTurboOver:(ccTime)Time
{
	[self unschedule:@selector(tickArrowCoolDownTimeTurboOver:)];
	arrowCoolDownTime_ = g_CfgGameArrowDataTable[g_RecordWeapSelected].cool_down_time;
}

- (void)tickCreateStar:(ccTime)Time
{
	[self unschedule:@selector(tickCreateStar:)];
	[self CreateStar];
}

- (void)tickItemFunctionStopTimeOver:(ccTime)Time
{
	std::list<sprite_game_enemy *>::iterator _EnemyIter;
	std::list<sprite_game_bomb *>::iterator _BombIter;

	[self unschedule:@selector(tickItemFunctionStopTimeOver:)];
	_EnemyIter = enemyPool_.begin();
	for (; _EnemyIter != enemyPool_.end(); _EnemyIter++)
	{
		[*_EnemyIter ItemFunctionTimeStopOver];
	}
	_BombIter = bombPool_.begin();
	for (; _BombIter != bombPool_.end(); _BombIter++)
	{
		[*_BombIter ItemFunctionTimeStopOver];
	}
}

- (bool)touchBegan:(CGPoint) Point
{
	int i;
	float _Degree;
	UICenterRect _HandleRect;
	std::list<SGameHandleArrow>::iterator _HandleArrowIter;
	CGPoint _Speed;
	std::list<sprite_game_enemy *>::iterator _TouchRegisterListIter;

	if (flagTouchLock_)
	{
		return;
	}

	_Touch = [Touch anyObject];
	_Point = [[CCDirector sharedDirector] convertToGL:[_Touch locationInView:[_Touch view]]];
	_Point = ConvertPositionToPositionInPixels(_Point);

	touchType_ = LAYER_GAME_OBJECT_TOUCH_TYPE_INVALID;

	/*check touch in parabola area
	*/
	_HandleRect.center = endPos_;
	_HandleRect.size = g_CfgGameParabolaTouch;
	if (uiPointInCenterRect(_Point, _HandleRect))
	{
		if (flagTouchLockArrow_)
		{
			return;
		}

		touchType_ = LAYER_GAME_OBJECT_TOUCH_TYPE_PARABOLA;

		/*enable preline
		*/
		_HandleArrowIter = currentHandleArrowTable_.begin();
		for (; _HandleArrowIter != currentHandleArrowTable_.end(); _HandleArrowIter++)
		{
			_HandleArrowIter->pre_line.active = true;
			_HandleArrowIter->pre_line.positionInPixels = [_HandleArrowIter->arrow GetPreLinePosition];
			_Speed = ptScalePoint_same(ccp(startPos_.x - endPos_.x, startPos_.y - endPos_.y), g_ParabolaSpeedScaleRatio);
			_Speed = ptRotatePoint_CGPoint(_Speed, -_HandleArrowIter->arrow.defaultRotate);
			[_HandleArrowIter->pre_line SetParabolaData:_Speed];
		}

		/*start hold arrow time track
		*/
		[self StartHoldArrowTimer:[currentHandleArrowTable_.begin()->arrow GetNextLevelHoldTime]];
	}
	/*check touch in linear area
	*/
	else if (uiPointInCenterRect(_Point, g_CfgGameLinearTouch))
	{
		if (flagTouchLockArrow_)
		{
			return;
		}

		touchType_ = LAYER_GAME_OBJECT_TOUCH_TYPE_LINEAR;
		endPos_ = _Point;
		_Degree = CC_RADIANS_TO_DEGREES(atan((startPos_.x - endPos_.x) / (startPos_.y - endPos_.y)));
		[bow_ setRotation:_Degree];

		/*update handle arrow rotation and position
		*/
		_HandleArrowIter = currentHandleArrowTable_.begin();
		for (; _HandleArrowIter != currentHandleArrowTable_.end(); _HandleArrowIter++)
		{
			_HandleArrowIter->arrow.rotation = _HandleArrowIter->arrow.defaultRotate + _Degree;
			_HandleArrowIter->arrow.positionInPixels = [bow_ GetBowHandlePoint];
		}

		/*do auto drag animation
		*/
		[self AutoDragStart];

		/*start hold arrow time trac
		*/
		[self StartHoldArrowTimer:[currentHandleArrowTable_.begin()->arrow GetNextLevelHoldTime]];
	}
	/*check touch in item area
	*/
	else
	{
		if (flagTouchLockItem_)
		{
			return;
		}

		for (i = 0; i < ITEM_SELECT_MAX_COUNT; i++)
		{
			if (uiPointInCenterRect(_Point, item_[i].rect))
			{
				touchType_ = LAYER_GAME_OBJECT_TOUCH_TYPE_ITEM;
				break;
			}
		}
	}

	/*touch begin register list
	*/
	_TouchRegisterListIter = touchRegisterList_.begin();
	for (; _TouchRegisterListIter != touchRegisterList_.end(); _TouchRegisterListIter++)
	{
		[*_TouchRegisterListIter EventTouchBegin:_Point];
	}

	return true;
}

- (bool)touchMoved:(CGPoint) Point
{
	float _Drag, _Degree;
	UICenterRect _HandleRect;
	std::list<SGameHandleArrow>::iterator _HandleArrowIter;
	CGPoint _Speed;
	std::list<sprite_game_enemy *>::iterator _TouchRegisterListIter;

	if (flagTouchLock_)
	{
		return;
	}

	_Touch = [Touch anyObject];
	_Point = [[CCDirector sharedDirector] convertToGL:[_Touch locationInView:[_Touch view]]];
	_Point = ConvertPositionToPositionInPixels(_Point);

	switch (touchType_)
	{
	case LAYER_GAME_OBJECT_TOUCH_TYPE_INVALID:
		if (flagTouchLockArrow_)
		{
			return;
		}

		/*check touch in parabola area
		*/
		_HandleRect.center = endPos_;
		_HandleRect.size = g_CfgGameParabolaTouch;
		if (uiPointInCenterRect(_Point, _HandleRect))
		{
			if (flagTouchLockArrow_)
			{
				return;
			}

			touchType_ = LAYER_GAME_OBJECT_TOUCH_TYPE_PARABOLA;

			/*enable preline
			*/
			_HandleArrowIter = currentHandleArrowTable_.begin();
			for (; _HandleArrowIter != currentHandleArrowTable_.end(); _HandleArrowIter++)
			{
				_HandleArrowIter->pre_line.active = true;
				_HandleArrowIter->pre_line.positionInPixels = [_HandleArrowIter->arrow GetPreLinePosition];
				_Speed = ptScalePoint_same(ccp(startPos_.x - endPos_.x, startPos_.y - endPos_.y), g_ParabolaSpeedScaleRatio);
				_Speed = ptRotatePoint_CGPoint(_Speed, -_HandleArrowIter->arrow.defaultRotate);
				[_HandleArrowIter->pre_line SetParabolaData:_Speed];
			}

			/*start hold arrow time track
			*/
			[self StartHoldArrowTimer:[currentHandleArrowTable_.begin()->arrow GetNextLevelHoldTime]];
		}
		break;
	case LAYER_GAME_OBJECT_TOUCH_TYPE_PARABOLA:
		if (flagTouchLockArrow_)
		{
			return;
		}

		endPos_ = _Point;
		if (startPos_.y - 5 >= endPos_.y)
		{
			_Drag = ptPointDistance_CGPoint(startPos_, endPos_) - bow_.bowBaseLength;
			if (_Drag > 0)
			{
				/*update rotation
				*/
				_Degree = CC_RADIANS_TO_DEGREES(atan((startPos_.x - endPos_.x) / (startPos_.y - endPos_.y)));

				/*update bow rotation
				*/
				[bow_ setRotation:_Degree];

				/*update handle arrow rotation, position and preline
				*/
				_HandleArrowIter = currentHandleArrowTable_.begin();
				for (; _HandleArrowIter != currentHandleArrowTable_.end(); _HandleArrowIter++)
				{
					_HandleArrowIter->arrow.rotation = _HandleArrowIter->arrow.defaultRotate + _Degree;
					_HandleArrowIter->arrow.positionInPixels = [bow_ GetBowHandlePoint];
					_Speed = ptScalePoint_same(ccp(startPos_.x - endPos_.x, startPos_.y - endPos_.y), g_ParabolaSpeedScaleRatio);
					_Speed = ptRotatePoint_CGPoint(_Speed, -_HandleArrowIter->arrow.defaultRotate);
					[_HandleArrowIter->pre_line SetParabolaData:_Speed];
				}

				/*update drag distance
				*/
				_Drag *= dragDistanceRatio_;
				if ([currentHandleArrowTable_.begin()->arrow GetMaxDragLength] - bow_.bowBaseLength > _Drag)
				{
					bow_.dragDistance = _Drag;
				}
			}
		}
		else
		{
			touchType_ = LAYER_GAME_OBJECT_TOUCH_TYPE_INVALID;
			[self CancelControlArrowAction];
		}
		break;
	case LAYER_GAME_OBJECT_TOUCH_TYPE_LINEAR:
		if (flagTouchLockArrow_)
		{
			return;
		}

		endPos_ = _Point;
		if (uiPointInCenterRect(endPos_, g_CfgGameLinearTouch))
		{
			/*update rotation
			*/
			_Degree = CC_RADIANS_TO_DEGREES(atan((startPos_.x - endPos_.x) / (startPos_.y - endPos_.y)));

			/*update bow rotation
			*/
			[bow_ setRotation:_Degree];

			/*update arrow rotation and position
			*/
			_HandleArrowIter = currentHandleArrowTable_.begin();
			for (; _HandleArrowIter != currentHandleArrowTable_.end(); _HandleArrowIter++)
			{
				_HandleArrowIter->arrow.rotation = _HandleArrowIter->arrow.defaultRotate + _Degree;
				_HandleArrowIter->arrow.positionInPixels = [bow_ GetBowHandlePoint];
			}
		}
		else
		{
			touchType_ = LAYER_GAME_OBJECT_TOUCH_TYPE_INVALID;
			[self CancelControlArrowAction];
		}
		break;
	case LAYER_GAME_OBJECT_TOUCH_TYPE_ITEM:
		break;
	default:;
	}

	/*touch move register list
	*/
	_TouchRegisterListIter = touchRegisterList_.begin();
	for (; _TouchRegisterListIter != touchRegisterList_.end(); _TouchRegisterListIter++)
	{
		[*_TouchRegisterListIter EventTouchEnd:_Point];
	}
	
	return true;
}

- (bool)touchEnded:(CGPoint) Point
{
	int i;
	CGPoint _Speed;
	float _DragDistance;
	std::list<sprite_game_enemy *>::iterator _TouchRegisterListIter;

	if (nil != tutorial_)
	{
		[tutorial_ OnTouch];
		return;
	}

	if (nil != g_SpriteGameMenuGetItem)
	{
		[g_SpriteGameMenuGetItem TouchEnded:_Point];
		return;
	}

	if (flagTouchLock_)
	{
		return;
	}

	switch (touchType_)
	{
	case LAYER_GAME_OBJECT_TOUCH_TYPE_INVALID:
		break;
	case LAYER_GAME_OBJECT_TOUCH_TYPE_PARABOLA:
		if (flagTouchLockArrow_)
		{
			return;
		}

		_DragDistance = [self GetCurrentDragDistance];
		if (5 < _DragDistance)
		{
			/*release parabola
			*/
			_Speed = ptScalePoint_same(ccp(startPos_.x - endPos_.x, startPos_.y - endPos_.y), g_ParabolaSpeedScaleRatio);
			[self ReleaseParabolaArrow:_Speed];

			/*lock arrow control
			*/
			flagTouchLockArrow_ = true;
			[self EndHoldArrowTimer];
			[self BowReset];
		}
		else
		{
			/*drag distance less than zero, do not release arrow
			*/
			[self CancelControlArrowAction];
		}
		break;
	case LAYER_GAME_OBJECT_TOUCH_TYPE_LINEAR:
		if (flagTouchLockArrow_)
		{
			return;
		}

		if (flagLinearAutoDragComplete_)
		{
			[self ReleaseLinearArrow:800];
			[self AutoDragEnd];
			endPos_ = [bow_ GetBowHandlePoint];
		}
		else
		{
			flagLinearAutoDragCompleteRelease_ = true;
		}
		[self EndHoldArrowTimer];

		/*lock arrow control
		*/
		flagTouchLockArrow_ = true;
		break;
	case LAYER_GAME_OBJECT_TOUCH_TYPE_ITEM:
		if (flagTouchLockItem_)
		{
			return;
		}

		for (i = 0; i < ITEM_SELECT_MAX_COUNT; i++)
		{
			if (uiPointInCenterRect(_Point, item_[i].rect))
			{
				[self SelectItem:&item_[i]];
			}
		}
		break;
	default:;
	}

	_TouchRegisterListIter = touchRegisterList_.begin();
	for (; _TouchRegisterListIter != touchRegisterList_.end(); _TouchRegisterListIter++)
	{
		[*_TouchRegisterListIter EventTouchEnd:_Point];
	}

	return true;
}

- (void)MissionStart
{
	std::list<SGameHandleArrow>::iterator _HandleArrowIter;
	std::list<sprite_game_arrow *>::iterator _ArrowIter;

	/*touch data
	*/
	flagTouchLock_ = false;
	flagFunctionLock_ = false;
	flagTouchLockArrow_ = false;
	flagTouchLockItem_ = false;

	/*bow
	*/
	flagLinearAutoDrag_ = false;
	flagLinearAutoDragComplete_ = false;
	flagLinearAutoDragCompleteRelease_ = false;
	[bow_ runAction:[CCShow action]];
	[self BowReset];

	/*arrow
	*/
	_HandleArrowIter = currentHandleArrowTable_.begin();
	for (; currentHandleArrowTable_.end() != _HandleArrowIter; _HandleArrowIter++)
	{
		[self removeChild:_HandleArrowIter->arrow cleanup:TRUE];
		[self removeChild:_HandleArrowIter->pre_line cleanup:TRUE];
	}
	currentHandleArrowTable_.clear();
	_ArrowIter = arrowPool_.begin();
	for (; arrowPool_.end() != _ArrowIter; _ArrowIter++)
	{
		[self removeChild:*_ArrowIter cleanup:TRUE];
	}
	arrowPool_.clear();
	[self EndCoolDownArrowTimer];
	[self EndHoldArrowTimer];
	[self ReadyArrow];

	/*star
	*/
	star_ = nil;
	if (!g_RecordMission[g_ChapterMissionID].flag_star_special)
	{
		[self schedule:@selector(tickCreateStar:) interval:LAYER_GAME_OBJECT_CREATE_STAR_TIME];
	}

	/*item backup
	*/
	memcpy(itemCountCopy_, g_RecordItemCount, sizeof itemCountCopy_);
	[self UpdateItem];

	flagExplodeArrow_ = false;
	flagMultiArrowTimes_ = false;

	/*menu btn back
	*/
	[self ShowBtnMenu];

	/*music
	*/
	MusicLoad();
	MusicPlayGame();
}

- (void)MissonOver
{
	std::list<SGameHandleArrow>::iterator _HandleArrowIter;
	std::list<sprite_game_arrow *>::iterator _ArrowIter;
	std::list<sprite_game_enemy *>::iterator _EnemyIter;
	std::list<sprite_game_bomb *>::iterator _BombIter;
	std::list<sprite_game_swirl *>::iterator _SwirlIter;
	std::list<sprite_game_heart *>::iterator _HeartIter;

	/*stop timer*/
	[self unschedule:@selector(tickArrowCoolDown:)];

	/*touch*/
	flagTouchLock_ = true;
	flagFunctionLock_ = true;

	/*bow*/
	flagLinearAutoDrag_ = false;
	flagLinearAutoDragComplete_ = false;
	flagLinearAutoDragCompleteRelease_ = false;
	[bow_ runAction:[CCHide action]];

	/*arrow*/
	_HandleArrowIter = currentHandleArrowTable_.begin();
	for (; currentHandleArrowTable_.end() != _HandleArrowIter; _HandleArrowIter++)
	{
		[self removeChild:_HandleArrowIter->arrow cleanup:TRUE];
		[self removeChild:_HandleArrowIter->pre_line cleanup:TRUE];
	}
	currentHandleArrowTable_.clear();
	_ArrowIter = arrowPool_.begin();
	for (; arrowPool_.end() != _ArrowIter; _ArrowIter++)
	{
		[self removeChild:*_ArrowIter cleanup:TRUE];
	}
	arrowPool_.clear();
	[self EndCoolDownArrowTimer];
	[self EndHoldArrowTimer];

	/*enemy*/
	_EnemyIter = enemyPool_.begin();
	for (; enemyPool_.end() != _EnemyIter; _EnemyIter++)
	{
		[self removeChild:*_EnemyIter cleanup:TRUE];
	}
	enemyPool_.clear();

	if (nil != tailLeft_)
	{
		[self removeChild:tailLeft_ cleanup:TRUE];
		tailLeft_ = nil;
	}
	if (nil != tailRight_)
	{
		[self removeChild:tailRight_ cleanup:TRUE];
		tailRight_ = nil;
	}

	/*bomb*/
	_BombIter = bombPool_.begin();
	for (; bombPool_.end() != _BombIter; _BombIter++)
	{
		[self removeChild:*_BombIter cleanup:TRUE];
	}
	bombPool_.clear();

	/*swirl*/
	_SwirlIter = swirlPool_.begin();
	for (; swirlPool_.end() != _SwirlIter; _SwirlIter++)
	{
		[self removeChild:*_SwirlIter cleanup:TRUE];
	}
	swirlPool_.clear();

	/*heart*/
	_HeartIter = heartPool_.begin();
	for (; heartPool_.end() != _HeartIter; _HeartIter++)
	{
		[self removeChild:*_HeartIter cleanup:TRUE];
	}
	heartPool_.clear();

	/*star*/
	if (nil != star_)
	{
		[self RemoveStar];
	}

	/*time bar*/
	[timeBar_ MissionOver];

	/*sync item
	*/
	memcpy(g_RecordItemCount, itemCountCopy_, sizeof itemCountCopy_);

	/*menu btn back
	*/
	[self HideBtnMenu];
}

- (void)Pause
{
	std::list<sprite_game_arrow *>::iterator _ArrowIter;
	std::list<sprite_game_enemy *>::iterator _EnemyIter;
	std::list<sprite_game_bomb *>::iterator _BombIter;
	std::list<sprite_game_swirl *>::iterator _SwirlIter;
	std::list<sprite_game_heart *>::iterator _HeartIter;

	[self pauseSchedulerAndActions];

	/*bow
	*/
	[bow_ Pause];

	/*arrow
	*/
	_ArrowIter = arrowPool_.begin();
	for (; _ArrowIter != arrowPool_.end(); _ArrowIter++)
	{
		[*_ArrowIter Pause];
	}

	/*enemy
	*/
	_EnemyIter = enemyPool_.begin();
	for (; _EnemyIter != enemyPool_.end(); _EnemyIter++)
	{
		[*_EnemyIter Pause];
	}

	/*bomb
	*/
	_BombIter = bombPool_.begin();
	for (; _BombIter != bombPool_.end(); _BombIter++)
	{
		[*_BombIter Pause];
	}

	/*swirl
	*/
	_SwirlIter = swirlPool_.begin();
	for (; _SwirlIter != swirlPool_.end(); _SwirlIter++)
	{
		[*_SwirlIter Pause];
	}

	/*heart
	*/
	_HeartIter = heartPool_.begin();
	for (; _HeartIter != heartPool_.end(); _HeartIter++)
	{
		[*_HeartIter Pause];
	}
}

- (void)Resume
{
	std::list<sprite_game_arrow *>::iterator _ArrowIter;
	std::list<sprite_game_enemy *>::iterator _EnemyIter;
	std::list<sprite_game_bomb *>::iterator _BombIter;
	std::list<sprite_game_swirl *>::iterator _SwirlIter;
	std::list<sprite_game_heart *>::iterator _HeartIter;

	[self resumeSchedulerAndActions];

	/*bow
	*/
	[bow_ Resume];

	/*arrow
	*/
	_ArrowIter = arrowPool_.begin();
	for (; _ArrowIter != arrowPool_.end(); _ArrowIter++)
	{
		[*_ArrowIter Resume];
	}

	/*enemy
	*/
	_EnemyIter = enemyPool_.begin();
	for (; _EnemyIter != enemyPool_.end(); _EnemyIter++)
	{
		[*_EnemyIter Resume];
	}

	/*bomb
	*/
	_BombIter = bombPool_.begin();
	for (; _BombIter != bombPool_.end(); _BombIter++)
	{
		[*_BombIter Resume];
	}

	/*swirl
	*/
	_SwirlIter = swirlPool_.begin();
	for (; _SwirlIter != swirlPool_.end(); _SwirlIter++)
	{
		[*_SwirlIter Resume];
	}

	/*heart
	*/
	_HeartIter = heartPool_.begin();
	for (; _HeartIter != heartPool_.end(); _HeartIter++)
	{
		[*_HeartIter Resume];
	}

	/*show btn
	*/
	[self ShowBtnMenu];
}

- (void)MissionWin
{
	/*music
	*/
	MusicPlayGameWin();
}

- (void)MissionLose
{
	/*music
	*/
	MusicPlayGameFail();
}

- (void)ActionPreview
{
	[self runAction:[CCShow action]];
	[self schedule:@selector(tickActionPreviewOver:) interval:MISSION_START_PLAY_TIME];
	[bow_ ActionPreview];
}

- (void)ActionToturialMain
{
	flagTouchLock_ = true;
	flagFunctionLock_ = true;

	tutorial_ = [[sprite_game_tutorial alloc] initSpriteGameTutorial:SPRITE_GAME_TUTORIAL_TYPE_MAIN];
	[self addChild:tutorial_ z:Z_ORDER_TOTURIAL];
	[tutorial_ release];


}

- (void)ActionToturialMainOver
{
	flagTouchLock_ = false;
	flagFunctionLock_ = false;

	[self removeChild:tutorial_ cleanup:TRUE];
	tutorial_ = nil;
	CMgrGameMission::Instance()->ToturialCreateHeart();
}

- (void)ActionToturialHeartAppear
{
	flagTouchLock_ = true;
	flagFunctionLock_ = true;

	tutorial_ = [[sprite_game_tutorial alloc] initSpriteGameTutorial:SPRITE_GAME_TUTORIAL_TYPE_HEART_APPEAR];
	[self addChild:tutorial_ z:Z_ORDER_TOTURIAL];
	[tutorial_ release];
}

- (void)ActionToturialHeartAppearOver
{
	flagTouchLock_ = false;
	flagFunctionLock_ = false;

	[self removeChild:tutorial_ cleanup:TRUE];
	tutorial_ = nil;
}

- (void)ActionToturialHeartGet
{
	flagTouchLock_ = true;
	flagFunctionLock_ = true;

	tutorial_ = [[sprite_game_tutorial alloc] initSpriteGameTutorial:SPRITE_GAME_TUTORIAL_TYPE_HEART_GET];
	[self addChild:tutorial_ z:Z_ORDER_TOTURIAL];
	[tutorial_ release];
}

- (void)ActionToturialHeartGetOver
{
	flagTouchLock_ = false;
	flagFunctionLock_ = false;

	[self removeChild:tutorial_ cleanup:TRUE];
	tutorial_ = nil;
	CMgrGameMission::Instance()->ToturialCreateEnemy();
}

- (void)ActionToturialEnemy
{
	flagTouchLock_ = true;
	flagFunctionLock_ = true;

	tutorial_ = [[sprite_game_tutorial alloc] initSpriteGameTutorial:SPRITE_GAME_TUTORIAL_TYPE_ENEMY];
	[self addChild:tutorial_ z:Z_ORDER_TOTURIAL];
	[tutorial_ release];
}

- (void)ActionToturialEnemyOver
{
	flagTouchLock_ = false;
	flagFunctionLock_ = false;

	[self removeChild:tutorial_ cleanup:TRUE];
	tutorial_ = nil;
}

- (void)ActionToturialOver
{
	flagTouchLock_ = true;
	flagFunctionLock_ = true;

	tutorial_ = [[sprite_game_tutorial alloc] initSpriteGameTutorial:SPRITE_GAME_TUTORIAL_TYPE_OVER];
	[self addChild:tutorial_ z:Z_ORDER_TOTURIAL];
	[tutorial_ release];
}

- (void)ActionToturialOverOver
{
	flagTouchLock_ = false;
	flagFunctionLock_ = false;

	[self removeChild:tutorial_ cleanup:TRUE];
	tutorial_ = nil;

	CMgrGameMission::Instance()->ToturialOver();
}

- (void)CancelControlArrowAction
{
	std::list<SGameHandleArrow>::iterator _HandleArrowIter;

	/*clear control arrow
	*/
	_HandleArrowIter = currentHandleArrowTable_.begin();
	for (; _HandleArrowIter != currentHandleArrowTable_.end(); _HandleArrowIter++)
	{
		[self removeChild:_HandleArrowIter->arrow cleanup:true];
		[self removeChild:_HandleArrowIter->pre_line cleanup:true];
	}
	currentHandleArrowTable_.clear();

	[self EndHoldArrowTimer];
	[self BowReset];
	[self ReadyArrow];
}

- (float)GetCurrentDragDistance
{
	return ptPointDistance_CGPoint(startPos_, endPos_) - bow_.bowBaseLength;
}

- (CGPoint)GetCurrentArrowHandlePoint
{
	CGPoint _Point;

	_Point = ccp(0.0f, -(bow_.bowBaseLength + bow_.dragDistance));
	_Point = ptRotatePoint_CGPoint(_Point, -CC_DEGREES_TO_RADIANS(bow_.rotation));
	_Point.x += startPos_.x;
	_Point.y += startPos_.y;
	return _Point;
}

- (void)AutoDragStart
{
	flagLinearAutoDrag_ = true;
	flagLinearAutoDragComplete_ = false;
	flagLinearAutoDragCompleteRelease_ = false;
}

- (void)AutoDragEnd
{
	flagLinearAutoDrag_ = false;
	flagLinearAutoDragComplete_ = false;
	flagLinearAutoDragCompleteRelease_ = false;
}

- (void)AutoDragComplete
{
	flagLinearAutoDragComplete_ = true;
}

- (void)BowReset
{
	bow_.rotation = 0.0f;
	bow_.dragDistance = 0.0f;
	endPos_ = [bow_ GetBowHandlePoint];
}

- (std::list<sprite_game_arrow *> *)GetArrowPool
{
	return &arrowPool_;
}

- (void)ReadyArrow
{
	int i;
	std::list<SGameHandleArrow>::iterator _HandleArrowIter;
	SGameHandleArrow _NewArrow;
	float _MaxArrowMove;
	float _DragDistance;

	/*clear exsite arrow
	*/
	_HandleArrowIter = currentHandleArrowTable_.begin();
	for (; _HandleArrowIter != currentHandleArrowTable_.end(); _HandleArrowIter++)
	{
		[self removeChild:_HandleArrowIter->arrow cleanup:TRUE];
		[self removeChild:_HandleArrowIter->pre_line cleanup:TRUE];
	}
	currentHandleArrowTable_.clear();

	/*create new arrow
	*/
	if (flagMultiArrowTimes_)
	{
		for (i = 0; i < 5; i++)
		{
			/*arrow
			*/
			_NewArrow.arrow = [[sprite_game_arrow alloc] initSpriteGameArrow:[bow_ GetArrowType]];
			[self addChild:_NewArrow.arrow z:Z_ORDER_ARROW];
			[_NewArrow.arrow release];
			_NewArrow.arrow.positionInPixels = [bow_ GetBowHandlePoint];
			_NewArrow.arrow.defaultRotate = -10.0f + i * 5.0f;
			_NewArrow.arrow.rotation = _NewArrow.arrow.defaultRotate;

			/*pre line
			*/
			_NewArrow.pre_line = [[sprite_game_arrow_pre_line alloc] initSpriteGameArrowPreLine];
			[self addChild:_NewArrow.pre_line];
			[_NewArrow.pre_line release];
			_NewArrow.pre_line.active = false;
			currentHandleArrowTable_.push_back(_NewArrow);

			if (flagExplodeArrow_)
			{
				_NewArrow.arrow.flagExplode = true;
			}
		}
	}
	else
	{
		/*arrow
		*/
		_NewArrow.arrow = [[sprite_game_arrow alloc] initSpriteGameArrow:[bow_ GetArrowType]];
		[self addChild:_NewArrow.arrow z:Z_ORDER_ARROW];
		[_NewArrow.arrow release];
		_NewArrow.arrow.positionInPixels = [bow_ GetBowHandlePoint];
		_NewArrow.arrow.defaultRotate = 0.0f;
		_NewArrow.arrow.rotation = _NewArrow.arrow.defaultRotate;

		/*pre line
		*/
		_NewArrow.pre_line = [[sprite_game_arrow_pre_line alloc] initSpriteGameArrowPreLine];
		[self addChild:_NewArrow.pre_line];
		[_NewArrow.pre_line release];
		_NewArrow.pre_line.active = false;
		currentHandleArrowTable_.push_back(_NewArrow);

		if (flagExplodeArrow_)
		{
			_NewArrow.arrow.flagExplode = true;
		}
	}

	/*update bow ratio
	*/
	/*parabola speed ratio*/
	_MaxArrowMove = g_ScrrenSize.height - startPos_.y + bow_.bowBaseLength + [currentHandleArrowTable_.front().arrow GetMaxDragLength] + g_ScrrenSize.height * 0.25;
	_DragDistance = startPos_.y - bow_.bowBaseLength;
	InitParabolaSpeedRatio(_MaxArrowMove, _DragDistance);
	/*drag distance map ratio*/
	dragDistanceRatio_ = (float)([currentHandleArrowTable_.begin()->arrow GetMaxDragLength] - bow_.bowBaseLength) / (startPos_.y - bow_.bowBaseLength);

	/*unlock arrow control
	*/
	flagTouchLockArrow_ = false;

	/*clear item explode arrow effect
	*/
	if (flagExplodeArrow_)
	{
		flagExplodeArrow_ = false;
	}
}

- (void)ReleaseParabolaArrow:(CGPoint)Speed
{
	CGPoint _Speed;
	std::list<SGameHandleArrow>::iterator _HandleArrowIter;

	/*handle start movement
	*/
	_HandleArrowIter = currentHandleArrowTable_.begin();
	for (; _HandleArrowIter != currentHandleArrowTable_.end(); _HandleArrowIter++)
	{
		/*arrow
		*/
		[_HandleArrowIter->arrow CreateBody];
		_Speed = ptRotatePoint_CGPoint(Speed, -_HandleArrowIter->arrow.defaultRotate);
		[_HandleArrowIter->arrow StartParabolaMovement:[bow_ GetBowHandlePoint] And:_Speed];
		arrowPool_.push_back(_HandleArrowIter->arrow);

		/*pre line
		*/
		[self removeChild:_HandleArrowIter->pre_line cleanup:TRUE];
	}
	currentHandleArrowTable_.clear();

	/*reset bow
	*/
	[self BowReset];

	/*start cool down timer
	*/
	[self StartCoolDownArrowTimer];

	/*play bow release arrow animation
	*/
	[bow_ PlayAniRelease];

	/*check item multi arrow
	*/
	if (flagMultiArrowTimes_ > 0)
	{
		flagMultiArrowTimes_--;
	}
}

- (void)ReleaseLinearArrow:(float)Speed
{
	CGPoint _StartPos;
	CGPoint _EndPos;
	std::list<SGameHandleArrow>::iterator _HandleArrowIter;

	/*handle arrow start movement
	*/
	_HandleArrowIter = currentHandleArrowTable_.begin();
	for (; _HandleArrowIter != currentHandleArrowTable_.end(); _HandleArrowIter++)
	{
		/*body
		*/
		[_HandleArrowIter->arrow CreateBody];

		/*movement
		*/
		_StartPos = [bow_ GetBowHandlePoint];
		_EndPos = ccpSub(endPos_, _StartPos);
		_EndPos = ptRotatePoint_CGPoint(_EndPos, -_HandleArrowIter->arrow.defaultRotate);
		_EndPos = ccpAdd(_EndPos, _StartPos);
		[_HandleArrowIter->arrow StartLinearMovement:_StartPos And:_EndPos And:Speed];

		/*move to arrow pool
		*/
		arrowPool_.push_back(_HandleArrowIter->arrow);

		/*remove pre line
		*/
		[self removeChild:_HandleArrowIter->pre_line cleanup:TRUE];
	}
	currentHandleArrowTable_.clear();

	/*reset bow
	*/
	[self BowReset];

	/*start cool down timer
	*/
	[self StartCoolDownArrowTimer];

	/*play bow release arrow animation
	*/
	[bow_ PlayAniRelease];

	/*check item multi arrow
	*/
	if (flagMultiArrowTimes_ > 0)
	{
		flagMultiArrowTimes_--;
	}
}

- (void)RemoveArrow:(sprite_game_arrow *)Arrow
{
	[self removeChild:Arrow cleanup:TRUE];
	arrowPool_.remove(Arrow);
}

- (void)ClearArrow
{
	std::list<sprite_game_arrow *>::iterator _Iter;

	_Iter = arrowPool_.begin();
	for (; _Iter != arrowPool_.end(); _Iter++)
	{
		[self removeChild:*_Iter cleanup:TRUE];
	}
	arrowPool_.clear();
}

- (void)StartCoolDownArrowTimer
{
	id _ProcessAction;
	CCCallFuncN *_CallBackTimeUp;
	CCSequence *_Seq;

	_ProcessAction = [CCProgressFromTo actionWithDuration:arrowCoolDownTime_ from:100 to:0];
	_CallBackTimeUp = [CCCallFuncN actionWithTarget:self selector:@selector(CallBackCoolDownTimerOver:)];
	_Seq = [CCSequence actions:_ProcessAction, _CallBackTimeUp, nil];
	[timerFlagCoolDown_ runAction:_Seq];
	[timerFlagCoolDown_ runAction:[CCShow action]];
}

- (void)EndCoolDownArrowTimer
{
	[timerFlagCoolDown_ stopAllActions];
	[timerFlagCoolDown_ runAction:[CCHide action]];
}

- (void)StartHoldArrowTimer:(float)HoldTime
{
	id _ProcessAction;
	CCCallFuncN *_CallBackTimeUp;
	CCSequence *_Seq;

	_ProcessAction = [CCProgressFromTo actionWithDuration:HoldTime from:0 to:100];
	_CallBackTimeUp = [CCCallFuncN actionWithTarget:self selector:@selector(CallBackLevelUpTimerOver:)];
	_Seq = [CCSequence actions:_ProcessAction, _CallBackTimeUp, nil];
	[timerFlagLevelUp_ runAction:_Seq];
	[timerFlagLevelUp_ runAction:[CCShow action]];
}

- (void)EndHoldArrowTimer
{
	[timerFlagLevelUp_ stopAllActions];
	[timerFlagLevelUp_ runAction:[CCHide action]];
}

- (void)Boss3ClearArrow
{
	std::list<SGameHandleArrow>::iterator _HandleArrowIter;
	std::list<sprite_game_arrow *>::iterator _ArrowIter;

	_HandleArrowIter = currentHandleArrowTable_.begin();
	for (; currentHandleArrowTable_.end() != _HandleArrowIter; _HandleArrowIter++)
	{
		[self removeChild:_HandleArrowIter->arrow cleanup:TRUE];
		[self removeChild:_HandleArrowIter->pre_line cleanup:TRUE];
	}
	currentHandleArrowTable_.clear();
	_ArrowIter = arrowPool_.begin();
	for (; arrowPool_.end() != _ArrowIter; _ArrowIter++)
	{
		[self removeChild:*_ArrowIter cleanup:TRUE];
	}
	arrowPool_.clear();
	[self EndCoolDownArrowTimer];
	[self EndHoldArrowTimer];
	[g_LayerGameObject BowReset];
}

- (void)AddEnemy:(sprite_game_enemy *)Enemy
{
	switch (Enemy.type)
	{
	case ENEMY_TYPE_0: case ENEMY_TYPE_1: case ENEMY_TYPE_2: case ENEMY_TYPE_3: case ENEMY_TYPE_4: case ENEMY_TYPE_5: case ENEMY_TYPE_6: case ENEMY_TYPE_7:
		[self addChild:Enemy z:Z_ORDER_ENEMY];
		break;
	case ENEMY_TYPE_BOSS_1: case ENEMY_TYPE_BOSS_2: case ENEMY_TYPE_BOSS_3:
		[self addChild:Enemy z:Z_ORDER_ENEMY_BOSS];
		break;
	default:;
	}
	[Enemy release];
	enemyPool_.push_back(Enemy);
}

- (void)RemoveEnemy:(sprite_game_enemy *)Enemy
{
	[self removeChild:Enemy cleanup:TRUE];
	enemyPool_.remove(Enemy);
}

- (void)ReorderEnemyMouth:(sprite_game_enemy *)Enemy
{
	[self reorderChild:Enemy z:Z_ORDER_ENEMY_MOUTH_ATTACK];
}

- (void)Boss1AddTail:(sprite_game_enemy_tail *)Left And:(sprite_game_enemy_tail *)Right
{
	tailLeft_ = Left;
	tailRight_ = Right;
	[self addChild:tailLeft_ z:Z_ORDER_ENEMY];
	[self addChild:tailRight_ z:Z_ORDER_ENEMY];
	[tailLeft_ release];
	[tailRight_ release];
}

- (void)Boss1StrongAttackBombMove:(std::list<sprite_game_bomb *> *)BombTable
{
	std::list<sprite_game_bomb *>::iterator _Iter;
	CGPoint _StartPos, _EndPos;
	float _Time;

	_Iter = BombTable->begin();
	for (; _Iter != BombTable->end(); _Iter++)
	{
		if (bombPool_.end() != std::find(bombPool_.begin(), bombPool_.end(), *_Iter))
		{
			_StartPos = (*_Iter).positionInPixels;
			_EndPos = [g_SpriteGameBridge GetBridgePositionByX:(*_Iter).positionInPixels.x];
			_Time = ptPointDistance_CGPoint((*_Iter).positionInPixels, _EndPos) / 90.0f;
			[*_Iter ActionAttack:_Time And:_EndPos];
		}
	}
}

- (void)Boss1StrongAttackCancel:(std::list<sprite_game_bomb *> *)BombTable
{
	std::list<sprite_game_bomb *>::iterator _Iter;

	_Iter = BombTable->begin();
	for (; _Iter != BombTable->end(); _Iter++)
	{
		if (bombPool_.end() != std::find(bombPool_.begin(), bombPool_.end(), *_Iter))
		{
			[self RemoveBomb:*_Iter];
		}
	}
}

- (void)Boss3SetZOrderOte:(sprite_game_enemy *)Boss3
{
	[self reorderChild:Boss3 z:Z_ORDER_BOSS_3_QTE];
}

- (void)Boss3SetZOrderNormal:(sprite_game_enemy *)Boss3
{
	[self reorderChild:Boss3 z:Z_ORDER_ENEMY];
}

- (void)RegisterTouchEvent:(sprite_game_enemy *)Enemy
{
	touchRegisterList_.push_back(Enemy);
}

- (void)UnregisterTouchEvent:(sprite_game_enemy *)Enemy
{
	touchRegisterList_.remove(Enemy);
}

- (void)AddBomb:(sprite_game_bomb *)Bomb
{
	[self addChild:Bomb z:Z_ORDER_BOMB];
	[Bomb release];
	bombPool_.push_back(Bomb);
}

- (void)RemoveBomb:(sprite_game_bomb *)Bomb
{
	[self removeChild:Bomb cleanup:TRUE];
	bombPool_.remove(Bomb);
}

- (void)Boss2ClearBomb
{
	std::list<sprite_game_bomb *>::iterator _BombIter;

	_BombIter = bombPool_.begin();
	for (; bombPool_.end() != _BombIter; _BombIter++)
	{
		[self removeChild:*_BombIter cleanup:TRUE];
	}
	bombPool_.clear();
}

- (void)AddSwirl:(sprite_game_swirl *)Swirl
{
	[self addChild:Swirl z:Z_ORDER_SWIRL];
	[Swirl release];
	swirlPool_.push_back(Swirl);
}

- (void)RemoveSwirl:(sprite_game_swirl *)Swril
{
	[self removeChild:Swril cleanup:TRUE];
	swirlPool_.remove(Swril);
}

- (void)AddHeart:(sprite_game_heart *)Heart
{
	[self addChild:Heart z:Z_ORDER_HEART];
	[Heart release];
	heartPool_.push_back(Heart);
}

- (void)RemoveHeart:(sprite_game_heart *)Heart
{
	[self removeChild:Heart cleanup:TRUE];
	heartPool_.remove(Heart);
}

- (void)CreateStar
{
	star_ = [[sprite_game_star alloc] initSpriteGameStar];
	[self addChild:star_];
	star_.positionInPixels = g_CfgGameScrrenArea[rand() % 9].center;
}

- (void)RemoveStar
{
	[star_ DestroyBody];
	[self removeChild:star_ cleanup:TRUE];
	star_ = nil;
}

- (void)UpdateItem
{
	int i;

	for (i = 0; i < ITEM_SELECT_MAX_COUNT; i++)
	{
		if (item_[i].type == -1)
		{
			[item_[i].item runAction:[CCHide action]];
			[item_[i].label runAction:[CCHide action]];
		}
		else
		{
			[item_[i].item setDisplayFrame:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithUTF8String:g_CfgItemTable.find(item_[i].type)->second.icon_path]]];
			[item_[i].label setString:[NSString stringWithFormat:@"%d", itemCountCopy_[item_[i].type]]];
			[item_[i].item runAction:itemCountCopy_[item_[i].type] == 0 ?[CCHide action]:[CCShow action]];
			[item_[i].label runAction:itemCountCopy_[item_[i].type] == 0 ?[CCHide action]:[CCShow action]];
		}
	}
}

- (void)SelectItem:(SGameItem *)Item
{
	std::list<SGameHandleArrow>::iterator _HandleArrowIter;

	if (Item->type == -1)
	{
		return;
	}
	if (itemCountCopy_[Item->type] == 0)
	{
		return;
	}

	switch (Item->type)
	{
	case 0 : /*防护罩*/
		if (!bridge_.flagCover)
		{
			itemCountCopy_[Item->type]--;
			[bridge_ ActionCover];
		}
		break;
	case 1 : /*时间+10秒*/
		itemCountCopy_[Item->type]--;
		[timeBar_ AddTime:10];
		break;
	case 2: /*时间静止10秒*/
		itemCountCopy_[Item->type]--;
		[self ItemFunctionTimeStop:10];
		break;
	case 3: /*无敌10秒*/
		itemCountCopy_[Item->type]--;
		[g_SpriteGameBridge ActionInvincible:10];
		break;
	case 4: /*多重箭*/
		itemCountCopy_[Item->type]--;
		flagMultiArrowTimes_ = 5;
		if (!flagTouchLockArrow_)
		{
			[self ReadyArrow];
		}
		break;
	case 5: /*爆裂箭*/
		itemCountCopy_[Item->type]--;
		if (currentHandleArrowTable_.size() > 0)
		{
			_HandleArrowIter = currentHandleArrowTable_.begin();
			for (; _HandleArrowIter != currentHandleArrowTable_.end(); _HandleArrowIter++)
			{
				_HandleArrowIter->arrow.flagExplode = true;
			}
		}
		else
		{
			flagExplodeArrow_ = true;
		}
		break;
	case 6: /*快速射击*/
		itemCountCopy_[Item->type]--;
		[self unschedule:@selector(tickArrowCoolDownTimeTurboOver:)];
		[self schedule:@selector(tickArrowCoolDownTimeTurboOver:) interval:10];
		arrowCoolDownTime_ = ARROW_COOL_DOWN_TIME_TURBO;
		break;
	default:;
	}
	[self UpdateItem];
}

- (void)ItemFunctionTimeStop:(float)Time
{
	std::list<sprite_game_enemy *>::iterator _EnemyIter;
	std::list<sprite_game_bomb *>::iterator _BombIter;

	[self unschedule:@selector(tickItemFunctionStopTimeOver:)];
	[self schedule:@selector(tickItemFunctionStopTimeOver:) interval:Time];
	_EnemyIter = enemyPool_.begin();
	for (; _EnemyIter != enemyPool_.end(); _EnemyIter++)
	{
		[*_EnemyIter ItemFunctionTimeStop];
	}
	_BombIter = bombPool_.end();
	for (; _BombIter != bombPool_.end(); _BombIter++)
	{
		[*_BombIter ItemFunctionTimeStop];
	}
}

- (void)BeginContact:(b2Contact *)Contact
{
	SContact _New;

	_New.fixture_a = Contact->GetFixtureA();
	_New.fixture_b = Contact->GetFixtureB();
	contactPool_.push_back(_New);
}

- (void)EndContact:(b2Contact *)Contact
{
	std::list<SContact>::iterator _Iter;

	_Iter = contactPool_.begin();
	for (; contactPool_.end() != _Iter; ++_Iter)
	{
		if (((*_Iter).fixture_a == Contact->GetFixtureA()) && ((*_Iter).fixture_b == Contact->GetFixtureB()))
		{
			contactPool_.erase(_Iter);
			return;
		}
	}
}

- (void)CheckContact:(SContact *)Contact
{
	int _ObjAType, _ObjBType;
	b2Fixture *_FixtureA, *_FixtureB;
	sprite_game_arrow *_StorageArrow[2];
	sprite_game_enemy *_StorageEnemy[2];
	sprite_game_bomb *_StorageBomb[2];
	sprite_game_heart *_StorageHeart[2];
	sprite_game_star *_StorageStar[2];

	_FixtureA = Contact->fixture_a;
	_FixtureB = Contact->fixture_b;

	for (int i = 0; i < 2; ++i)
	{
		_StorageArrow[i] = NULL;
		_StorageEnemy[i] = NULL;
		_StorageBomb[i] = NULL;
		_StorageHeart[i] = NULL;
	}

	_StorageArrow[0] = [self CheckCollisionFixtureIsArrow:_FixtureA];
	if (nil != _StorageArrow[0])
	{
		_ObjAType = COLLISION_TYPE_ARROW;
		goto CHECK_OBJ_B_;
	}
	_StorageEnemy[0] = [self CheckCollisionFixtureIsEnemy:_FixtureA];
	if (nil != _StorageEnemy[0])
	{
		_ObjAType = COLLISION_TYPE_ENEMY;
		goto CHECK_OBJ_B_;
	}
	_StorageBomb[0] = [self CheckCollisionFixtureIsBomb:_FixtureA];
	if (nil != _StorageBomb[0])
	{
		_ObjAType = COLLISION_TYPE_BOMB;
		goto CHECK_OBJ_B_;
	}
	_StorageHeart[0] = [self CheckCollisionFixtureIsHeart:_FixtureA];
	if (nil != _StorageHeart[0])
	{
		_ObjAType = COLLISION_TYPE_HEART;
		goto CHECK_OBJ_B_;
	}
	_StorageStar[0] = [self CheckCollisionFixtureIsStar:_FixtureA];
	if (nil != _StorageStar[0])
	{
		_ObjAType = COLLISION_TYPE_STAR;
		goto CHECK_OBJ_B_;
	}
	_ObjAType = COLLISION_TYPE_INVALID;

CHECK_OBJ_B_:
	_StorageArrow[1] = [self CheckCollisionFixtureIsArrow:_FixtureB];
	if (nil != _StorageArrow[1])
	{
		_ObjBType = COLLISION_TYPE_ARROW;
		goto EVENT_DISPATCH_;
	}
	_StorageEnemy[1] = [self CheckCollisionFixtureIsEnemy:_FixtureB];
	if (nil != _StorageEnemy[1])
	{
		_ObjBType = COLLISION_TYPE_ENEMY;
		goto EVENT_DISPATCH_;
	}
	_StorageBomb[1] = [self CheckCollisionFixtureIsBomb:_FixtureB];
	if (nil != _StorageBomb[1])
	{
		_ObjBType = COLLISION_TYPE_BOMB;
		goto EVENT_DISPATCH_;
	}
	_StorageHeart[1] = [self CheckCollisionFixtureIsHeart:_FixtureB];
	if (nil != _StorageHeart[1])
	{
		_ObjBType = COLLISION_TYPE_HEART;
		goto EVENT_DISPATCH_;
	}
	_StorageStar[1] = [self CheckCollisionFixtureIsStar:_FixtureB];
	if (nil != _StorageStar[1])
	{
		_ObjBType = COLLISION_TYPE_STAR;
		goto EVENT_DISPATCH_;
	}
	_ObjBType = COLLISION_TYPE_INVALID;

EVENT_DISPATCH_:
	switch (_ObjAType)
	{
	case COLLISION_TYPE_ARROW:
		switch (_ObjBType)
		{
		case COLLISION_TYPE_ENEMY:[self OnCollisionArrowAndEnemy:_StorageArrow[0] And:_StorageEnemy[1] And:_FixtureA And:_FixtureB]; break;
		case COLLISION_TYPE_BOMB:[self OnCollisionArrowAndBomb:_StorageArrow[0] And:_StorageBomb[1]]; break;
		case COLLISION_TYPE_HEART:[self OnCollisionArrowAndHeart:_StorageArrow[0] And:_StorageHeart[1]]; break;
		case COLLISION_TYPE_STAR:[self OnCollisionArrowAndStar:_StorageArrow[0] And:_StorageStar[1]]; break;
		default: break;
		}
		break;
	case COLLISION_TYPE_ENEMY:
		switch (_ObjBType)
		{
		case COLLISION_TYPE_ARROW:[self OnCollisionArrowAndEnemy:_StorageArrow[1] And:_StorageEnemy[0] And:_FixtureB And:_FixtureA]; break;
		case COLLISION_TYPE_HEART:[self OnCollisionEnemyAndHeart:_StorageEnemy[0] And:_StorageHeart[1]]; break;
		default: break;
		}
		break;
	case COLLISION_TYPE_BOMB:
		switch (_ObjBType)
		{
		case COLLISION_TYPE_ARROW:[self OnCollisionArrowAndBomb:_StorageArrow[1] And:_StorageBomb[0]]; break;
		default: break;
		}
		break;
	case COLLISION_TYPE_HEART:
		switch (_ObjBType)
		{
		case COLLISION_TYPE_ARROW:[self OnCollisionArrowAndHeart:_StorageArrow[1] And:_StorageHeart[0]]; break;
		case COLLISION_TYPE_ENEMY:[self OnCollisionEnemyAndHeart:_StorageEnemy[1] And:_StorageHeart[0]]; break;
		default: break;
		}
		break;
	case COLLISION_TYPE_STAR:
		switch (_ObjBType)
		{
		case COLLISION_TYPE_ARROW:[self OnCollisionArrowAndStar:_StorageArrow[1] And:_StorageStar[0]]; break;
		}
		break;
	default: break;
	}
}

- (sprite_game_arrow *)CheckCollisionFixtureIsArrow:(b2Fixture *)Fixture
{
	std::list<sprite_game_arrow *>::iterator _Iter;

	_Iter = arrowPool_.begin();
	for (; arrowPool_.end() != _Iter; ++_Iter)
	{
		if ([*_Iter IsMyFixtureArrow:Fixture])
		{
			return *_Iter;
		}
		if ([*_Iter IsMyFixtureExplode:Fixture])
		{
			return *_Iter;
		}
	}
	return nil;
}

- (sprite_game_enemy *)CheckCollisionFixtureIsEnemy:(b2Fixture *)Fixture
{
	std::list<sprite_game_enemy *>::iterator _Iter;

	_Iter = enemyPool_.begin();
	for (; enemyPool_.end() != _Iter; ++_Iter)
	{
		switch ((*_Iter).type)
		{
		case ENEMY_TYPE_0:
		case ENEMY_TYPE_1:
		case ENEMY_TYPE_2:
		case ENEMY_TYPE_3:
		case ENEMY_TYPE_4:
		case ENEMY_TYPE_6:
		case ENEMY_TYPE_7:
			if ([*_Iter IsBodyFixture:Fixture])
			{
				return *_Iter;
			}
			break;
		case ENEMY_TYPE_5:
			if ([*_Iter IsBodyFixture:Fixture])
			{
				return *_Iter;
			}
			if ([*_Iter IsArmorFixture:Fixture])
			{
				return *_Iter;
			}
			break;
		case ENEMY_TYPE_BOSS_1:
			if ([*_Iter IsBoss1HeadFixture:Fixture])
			{
				return *_Iter;
			}
			if ([*_Iter IsBoss1BodyFixture:Fixture])
			{
				return *_Iter;
			}
			if ([*_Iter IsBoss1TailFixture:Fixture])
			{
				return *_Iter;
			}
			break;
		case ENEMY_TYPE_BOSS_2:
			if ([*_Iter IsBodyFixture:Fixture])
			{
				return *_Iter;
			}
			if ([*_Iter IsBoss2SkullFixture:Fixture])
			{
				return *_Iter;
			}
			break;
		case ENEMY_TYPE_BOSS_3:
			if ([*_Iter IsBoss3HeadFixture:Fixture])
			{
				return *_Iter;
			}
			if ([*_Iter IsBoss3BodyFixture:Fixture])
			{
				return *_Iter;
			}
			if ([*_Iter IsBoss3AssFixture:Fixture])
			{
				return *_Iter;
			}
			break;
		}
	}
	return nil;
}

- (sprite_game_bomb *)CheckCollisionFixtureIsBomb:(b2Fixture *)Fixture
{
	std::list<sprite_game_bomb *>::iterator _Iter;

	_Iter = bombPool_.begin();
	for (; bombPool_.end() != _Iter; ++_Iter)
	{
		if ([*_Iter IsMyFixture:Fixture])
		{
			return *_Iter;
		}
	}
	return nil;
}

- (sprite_game_heart *)CheckCollisionFixtureIsHeart:(b2Fixture *)Fixture
{
	std::list<sprite_game_heart *>::iterator _Iter;

	_Iter = heartPool_.begin();
	for (; heartPool_.end() != _Iter; ++_Iter)
	{
		if ([*_Iter IsMyFixture:Fixture])
		{
			return *_Iter;
		}
	}
	return nil;
}

- (sprite_game_star *)CheckCollisionFixtureIsStar:(b2Fixture *)Fixture
{
	if (nil == star_)
	{
		return nil;
	}
	else if ([star_ IsMyFixture:Fixture])
	{
		return star_;
	}
	else
	{
		return nil;
	}
}

- (void)OnCollisionArrowAndEnemy:(sprite_game_arrow *)Arrow And:(sprite_game_enemy *)Enemy And:(b2Fixture *)ArrowFixture And:(b2Fixture *)EnemyFixture
{
	switch (Enemy.type)
	{
	case ENEMY_TYPE_0:
	case ENEMY_TYPE_1:
	case ENEMY_TYPE_2:
	case ENEMY_TYPE_3:
	case ENEMY_TYPE_4:
	case ENEMY_TYPE_6:
	case ENEMY_TYPE_7:
		if (Arrow.flagExplode)
		{
			switch (Arrow.state)
			{
			case ARROW_STATE_CONTROL: return;

			case ARROW_STATE_MOVE: goto FLAG_ARROW_EXPLODE_; break;
			case ARROW_STATE_INVALID: return;

			case ARROW_STATE_EXPLODE:
				if ([Enemy Damage:Arrow.attackPoint])
				{
					goto FLAG_KILL_ENEMY_;
				}
				else
				{
					if (Z_ORDER_ENEMY_MOUTH_ATTACK != Enemy.zOrder)
					{
						[self reorderChild:Enemy z:Z_ORDER_ENEMY];
					}
					Arrow.perforation--;
					goto FLAG_ARROW_CONTROL_;
				}
				break;
			case ARROW_STATE_EXPLODE_OVER: return;

			default: return;
			}
		}
		else if ([Enemy Damage:Arrow.attackPoint])
		{
			goto FLAG_KILL_ENEMY_;
		}
		else
		{
			if (Z_ORDER_ENEMY_MOUTH_ATTACK != Enemy.zOrder)
			{
				[self reorderChild:Enemy z:Z_ORDER_ENEMY];
			}
			Arrow.perforation--;
			goto FLAG_ARROW_CONTROL_;
		}
		break;
	case ENEMY_TYPE_5:
		if (Arrow.flagExplode)
		{
			switch (Arrow.state)
			{
			case ARROW_STATE_CONTROL: return;

			case ARROW_STATE_MOVE: goto FLAG_ARROW_EXPLODE_; break;
			case ARROW_STATE_INVALID: return;

			case ARROW_STATE_EXPLODE:
				if (Arrow.positionInPixels.y > Enemy.positionInPixels.y)
				{
					if ([Enemy Damage:Arrow.attackPoint])
					{
						goto FLAG_KILL_ENEMY_;
					}
					else
					{
						[self reorderChild:Enemy z:Z_ORDER_ENEMY];
						Arrow.perforation--;
						goto FLAG_ARROW_CONTROL_;
					}
				}
				else
				{
					return;
				}
				break;
			case ARROW_STATE_EXPLODE_OVER: return;

			default: return;
			}
		}
		else if ([Enemy IsBodyFixture:EnemyFixture])
		{
			if ([Enemy Damage:Arrow.attackPoint])
			{
				goto FLAG_KILL_ENEMY_;
			}
			else
			{
				Arrow.perforation--;
				goto FLAG_ARROW_CONTROL_;
			}
		}
		else if ([Enemy IsArmorFixture:EnemyFixture])
		{
			[Enemy PlayEffectCover];
			goto FLAG_ARROW_INVALID_;
		}
		else
		{
			assert(false);
		}
		break;
	case ENEMY_TYPE_BOSS_1:
		if (Arrow.flagExplode)
		{
			switch (Arrow.state)
			{
			case ARROW_STATE_CONTROL: return;

			case ARROW_STATE_MOVE: goto FLAG_ARROW_EXPLODE_; break;
			case ARROW_STATE_INVALID: return;

			case ARROW_STATE_EXPLODE:
				if ([Enemy IsBoss1HeadFixture:EnemyFixture])
				{
					if ([Enemy IsInvincible])
					{
						goto FLAG_ARROW_INVALID_;
					}
					else if ([Enemy Damage:Arrow.attackPoint])
					{
						goto FLAG_KILL_ENEMY_;
					}
					else
					{
						Arrow.perforation = 0;
						goto FLAG_ARROW_CONTROL_;
					}
				}
				else if ([Enemy IsBoss1BodyFixture:EnemyFixture])
				{
					if ([Enemy IsInvincible])
					{
						goto FLAG_ARROW_INVALID_;
					}
					else if ([Enemy Damage:Arrow.attackPoint])
					{
						goto FLAG_KILL_ENEMY_;
					}
					else
					{
						Arrow.perforation = 0;
						goto FLAG_ARROW_CONTROL_;
					}
				}
				else if ([Enemy IsBoss1TailFixture:EnemyFixture])
				{
					if ([Enemy DamageBoss1Tail:Arrow.attackPoint And:EnemyFixture])
					{
						Arrow.perforation = 0;
						goto FLAG_ARROW_CONTROL_;
					}
					else
					{
						goto FLAG_ARROW_INVALID_;
					}
				}
				else
				{
					assert(false);
				}
				break;
			case ARROW_STATE_EXPLODE_OVER: return;

			default: return;
			}
		}
		else if ([Enemy IsBoss1HeadFixture:EnemyFixture])
		{
			if ([Enemy IsInvincible])
			{
				goto FLAG_ARROW_INVALID_;
			}
			else if ([Enemy Damage:Arrow.attackPoint])
			{
				goto FLAG_KILL_ENEMY_;
			}
			else
			{
				Arrow.perforation = 0;
				goto FLAG_ARROW_CONTROL_;
			}
		}
		else if ([Enemy IsBoss1BodyFixture:EnemyFixture])
		{
			if ([Enemy IsInvincible])
			{
				goto FLAG_ARROW_INVALID_;
			}
			else if ([Enemy Damage:Arrow.attackPoint])
			{
				goto FLAG_KILL_ENEMY_;
			}
			else
			{
				Arrow.perforation = 0;
				goto FLAG_ARROW_CONTROL_;
			}
		}
		else if ([Enemy IsBoss1TailFixture:EnemyFixture])
		{
			if ([Enemy DamageBoss1Tail:Arrow.attackPoint And:EnemyFixture])
			{
				Arrow.perforation = 0;
				goto FLAG_ARROW_CONTROL_;
			}
			else
			{
				goto FLAG_ARROW_INVALID_;
			}
		}
		else
		{
			assert(false);
		}
		break;
	case ENEMY_TYPE_BOSS_2:
		if (Arrow.flagExplode)
		{
			switch (Arrow.state)
			{
			case ARROW_STATE_CONTROL: return;

			case ARROW_STATE_MOVE: goto FLAG_ARROW_EXPLODE_; break;
			case ARROW_STATE_INVALID: return;

			case ARROW_STATE_EXPLODE:
				if ([Enemy IsBodyFixture:EnemyFixture])
				{
					if ([Enemy IsInvincible])
					{
						goto FLAG_ARROW_INVALID_;
					}
					else if ([Enemy Damage:Arrow.attackPoint])
					{
						goto FLAG_KILL_ENEMY_;
					}
					else
					{
						Arrow.perforation = 0;
						goto FLAG_ARROW_CONTROL_;
					}
				}
				else if ([Enemy IsBoss2SkullFixture:EnemyFixture])
				{
					if ([Enemy DamageBoss2Skull:Arrow.attackPoint And:EnemyFixture])
					{
						Arrow.perforation = 0;
						if (Enemy.lifePoint <= 0)
						{
							goto FLAG_KILL_ENEMY_;
						}
						else
						{
							goto FLAG_ARROW_CONTROL_;
						}
					}
					else
					{
						goto FLAG_ARROW_INVALID_;
					}
				}
				else
				{
					assert(false);
				}
				break;
			case ARROW_STATE_EXPLODE_OVER: return;

			default: return;
			}
		}
		else if ([Enemy IsBodyFixture:EnemyFixture])
		{
			if ([Enemy IsInvincible])
			{
				goto FLAG_ARROW_INVALID_;
			}
			else if ([Enemy Damage:Arrow.attackPoint])
			{
				goto FLAG_KILL_ENEMY_;
			}
			else
			{
				Arrow.perforation = 0;
				goto FLAG_ARROW_CONTROL_;
			}
		}
		else if ([Enemy IsBoss2SkullFixture:EnemyFixture])
		{
			if ([Enemy DamageBoss2Skull:Arrow.attackPoint And:EnemyFixture])
			{
				Arrow.perforation = 0;
				if (Enemy.lifePoint <= 0)
				{
					goto FLAG_KILL_ENEMY_;
				}
				else
				{
					goto FLAG_ARROW_CONTROL_;
				}
			}
			else
			{
				goto FLAG_ARROW_INVALID_;
			}
		}
		else
		{
			assert(false);
		}
		break;
	case ENEMY_TYPE_BOSS_3:
		if (Arrow.flagExplode)
		{
			switch (Arrow.state)
			{
			case ARROW_STATE_CONTROL: return;

			case ARROW_STATE_MOVE: goto FLAG_ARROW_EXPLODE_; break;
			case ARROW_STATE_INVALID: return;

			case ARROW_STATE_EXPLODE:
				if ([Enemy IsBoss3HeadFixture:EnemyFixture])
				{
					if ([Enemy IsInvincible])
					{
						goto FLAG_ARROW_INVALID_;
					}
					else if ([Enemy Damage:Arrow.attackPoint])
					{
						goto FLAG_KILL_ENEMY_;
					}
					else
					{
						Arrow.perforation = 0;
						goto FLAG_ARROW_CONTROL_;
					}
				}
				else if ([Enemy IsBoss3BodyFixture:EnemyFixture])
				{
					if ([Enemy IsInvincible])
					{
						goto FLAG_ARROW_INVALID_;
					}
					else if ([Enemy Damage:Arrow.attackPoint])
					{
						goto FLAG_KILL_ENEMY_;
					}
					else
					{
						Arrow.perforation = 0;
						goto FLAG_ARROW_CONTROL_;
					}
				}
				else if ([Enemy IsBoss3AssFixture:EnemyFixture])
				{
					if ([Enemy IsInvincible])
					{
						goto FLAG_ARROW_INVALID_;
					}
					else if ([Enemy Damage:Arrow.attackPoint])
					{
						goto FLAG_KILL_ENEMY_;
					}
					else
					{
						Arrow.perforation = 0;
						goto FLAG_ARROW_CONTROL_;
					}
				}
				else
				{
					assert(false);
				}
				break;
			case ARROW_STATE_EXPLODE_OVER: return;

			default: return;
			}
		}
		else if ([Enemy IsBoss3HeadFixture:EnemyFixture])
		{
			if ([Enemy IsInvincible])
			{
				goto FLAG_ARROW_INVALID_;
			}
			else if ([Enemy Damage:Arrow.attackPoint])
			{
				goto FLAG_KILL_ENEMY_;
			}
			else
			{
				Arrow.perforation = 0;
				goto FLAG_ARROW_CONTROL_;
			}
		}
		else if ([Enemy IsBoss3BodyFixture:EnemyFixture])
		{
			if ([Enemy IsInvincible])
			{
				goto FLAG_ARROW_INVALID_;
			}
			else if ([Enemy Damage:Arrow.attackPoint])
			{
				goto FLAG_KILL_ENEMY_;
			}
			else
			{
				Arrow.perforation = 0;
				goto FLAG_ARROW_CONTROL_;
			}
		}
		else if ([Enemy IsBoss3AssFixture:EnemyFixture])
		{
			if ([Enemy IsInvincible])
			{
				goto FLAG_ARROW_INVALID_;
			}
			else if ([Enemy Damage:Arrow.attackPoint])
			{
				goto FLAG_KILL_ENEMY_;
			}
			else
			{
				Arrow.perforation = 0;
				goto FLAG_ARROW_CONTROL_;
			}
		}
		else
		{
			assert(false);
		}
		break;
	default: return;
	}

FLAG_KILL_ENEMY_:
	[Enemy DestroyBody];
	[Enemy ActionDie];
	if (Arrow.state == ARROW_STATE_MOVE)
	{
		Arrow.perforation--;
	}

FLAG_ARROW_CONTROL_:
	if ((Arrow.state == ARROW_STATE_MOVE) && (Arrow.perforation <= 0))
	{
		[self RemoveArrow:Arrow];
	}
	return;

FLAG_ARROW_INVALID_:
	[Arrow ActionInvalid];
	return;

FLAG_ARROW_EXPLODE_:
	[Arrow ActionExplode];
	return;
}

- (void)OnCollisionArrowAndHeart:(sprite_game_arrow *)Arrow And:(sprite_game_heart *)Heart
{
	if (Arrow.state == ARROW_STATE_MOVE)
	{
		[Heart DestroyBody];
		[Heart ActionDie];
	}
}

- (void)OnCollisionArrowAndStar:(sprite_game_arrow *)Arrow And:(sprite_game_star *)Star
{
	[self RemoveArrow:Arrow];
	[Star HitStar];
}

- (void)OnCollisionArrowAndBomb:(sprite_game_arrow *)Arrow And:(sprite_game_bomb *)Bomb
{
	if (Bomb.canBeDestroy)
	{
		[Bomb ActionDestroy];
	}
}

- (void)OnCollisionEnemyAndHeart:(sprite_game_enemy *)Arrow And:(sprite_game_heart *)Heart
{}

- (void)PutBox2dBodyToDestroyPool:(b2Body *)Body
{
	assert(NULL != Body);
	destroyBodyPool_.push_back(Body);
}

- (std::list<sprite_game_heart *> *)GetHeartPool
{
	return &heartPool_;
}

- (void)CallBackCoolDownTimerOver:(id)Sender
{
	[self ReadyArrow];
}

- (void)CallBackLevelUpTimerOver:(id)Sender
{
	std::list<SGameHandleArrow>::iterator _HandleArrowIter;

	_HandleArrowIter = currentHandleArrowTable_.begin();
	for (; _HandleArrowIter != currentHandleArrowTable_.end(); _HandleArrowIter++)
	{
		[_HandleArrowIter->arrow AddLevel];
	}
	if (![currentHandleArrowTable_.begin()->arrow IsMaxLevel])
	{
		[self StartHoldArrowTimer:[currentHandleArrowTable_.begin()->arrow GetNextLevelHoldTime]];
	}
	else
	{
		[timerFlagLevelUp_ runAction:[CCHide action]];
	}
}

- (void)CallBackBtnMenu:(id)Sender
{
	if (flagFunctionLock_)
	{
		return;
	}

	/*effect
	*/
	EffectButton();

	/*action
	*/
	[self HideBtnMenu];

	/*pause
	*/
	[g_SceneGame Pause];

	/*menu
	*/
	g_LayerGameMenu = [[layer_game_menu alloc] initLayerGameMenu:GAME_MENU_STATE_PAUSE];
	[g_SceneGame addChild:g_LayerGameMenu];
	[g_LayerGameMenu release];
}

- (void)ShowBtnMenu
{
	flagTouchLock_ = false;
	flagFunctionLock_ = false;
	[btnMenu_ runAction:[action_move_in_pixel actionWithDuration:BTN_MOVE_TIME position:ccp(g_ScrrenSize.width, 0.0f)]];
}

- (void)HideBtnMenu
{
	flagTouchLock_ = true;
	flagFunctionLock_ = true;
	[btnMenu_ runAction:[action_move_in_pixel actionWithDuration:BTN_MOVE_TIME position:ccp(g_ScrrenSize.width + btnMenu_.contentSizeInPixels.width, 0.0f)]];
}

@end